
#include "macros.h"
#include "storage.h"
#include "ex_eeprom.h"
#include "entrys.h"
#include "outf.h"
#include "memmap.h"
#include "debug.h"

/* 
	Storage organization:
 for each type of storage data need create address range - directory;

   Storage rule:
	first byte of entry into storage must be less than	0xFE in other case this entry is free for write;  
 */

storage_class_t storage;

unsigned int storage_index;

/* registration of all directories (storage_directory_properties_t)*/
const storage_directory_properties_t directories[] =
{
	{phone_add, phone_find, phone_print, ADDR_LIST_0, sizeof(storage_entry_phone_t),PHONE_LIST_0_COUNT },
	{phone_add, phone_find, phone_print, ADDR_LIST_1, sizeof(storage_entry_phone_t),PHONE_LIST_1_COUNT }
};

#define   STORAGE_DIRECTORY_COUNT		(sizeof(directories)/sizeof(storage_directory_properties_t))


int storage_find_free( unsigned int directory ) /* return addr of free place for the entry */
{	
	if ( directory >= STORAGE_DIRECTORY_COUNT )
		return STORAGE_ERR__WRONG_DIRECTORY;

	unsigned int addr = DIR_PROP.directory_addr;
	unsigned int end_addr = addr + (DIR_PROP.entry_size * DIR_PROP.entrys_count); 
	unsigned char stor_byte;

	storage_index = directory;

	for ( ; addr < end_addr; addr += DIR_PROP.entry_size )  
	{
		storage.Read(addr, &stor_byte, 1);
		if ( stor_byte >= STORAGE_FREE_ENTRY_TOKEN )
			return addr;
	}

	return STORAGE_ERR__NO_FRE_MEM;
}

/* return: how many entrys into directory */
int storage_entrys_counter( unsigned int directory ) /* return addr of free place for the entry */
{	
	if ( directory >= STORAGE_DIRECTORY_COUNT )
		return STORAGE_ERR__WRONG_DIRECTORY;

	unsigned int entrys_counter = 0;
	unsigned int addr = DIR_PROP.directory_addr;
	unsigned int end_addr = addr + (DIR_PROP.entry_size * DIR_PROP.entrys_count); 
	unsigned char stor_byte;

	storage_index = directory;

	for ( ; addr < end_addr; addr += DIR_PROP.entry_size )  
	{
		storage.Read(addr, &stor_byte, 1);
		
		if ( stor_byte < STORAGE_FREE_ENTRY_TOKEN )
		{
			entrys_counter++;
		}
	}

	//DBG("\n%s; #####>>> entrys_counter: %d\n",__FUNCTION__,entrys_counter); //Dima 
	return entrys_counter;
}

/* return -1 if fail */
static int storage_add( unsigned int directory, void *entry)
{
	if ( directory >= STORAGE_DIRECTORY_COUNT )
		return STORAGE_ERR__WRONG_DIRECTORY;

	storage_index = directory;
	
	return DIR_PROP.add(entry);
}

/* return addr of entry or STORAGE_ERR__ENTRY_NOT_FOUND */
static int storage_find ( unsigned int directory, void *ref)
{
	if ( directory >= STORAGE_DIRECTORY_COUNT )
		return STORAGE_ERR__WRONG_DIRECTORY;
	
	storage_index = directory;
	
	return DIR_PROP.find(ref);
}

/* return 1 if OK or STORAGE_ERR__ENTRY_NOT_FOUND in other case */
static int storage_delete_entry(unsigned int directory, void *entry)
{
	if ( directory >= STORAGE_DIRECTORY_COUNT )
		return STORAGE_ERR__WRONG_DIRECTORY;

	storage_index = directory;

	int del_addr = DIR_PROP.find(entry);
	
	if ( del_addr == STORAGE_ERR__ENTRY_NOT_FOUND ) 
		return STORAGE_ERR__ENTRY_NOT_FOUND;
	
	unsigned char wb = STORAGE_FREE_ENTRY_TOKEN;
	
	return storage.Write(del_addr, &wb, 1);
}

/* return 0 if all mem was set  */
static int storage_delete_directory ( unsigned int directory )
{
	if ( directory >= STORAGE_DIRECTORY_COUNT )
		return STORAGE_ERR__WRONG_DIRECTORY;
	
	storage_index = directory;
	
	unsigned int directory_size = DIR_PROP.entry_size * DIR_PROP.entrys_count;

	return storage.mset(DIR_PROP.directory_addr, 0xFF, directory_size);
}

static int storage_del_all( void ) /* return 0 or -1 if fail */
{
	unsigned int i, storage_size = 0;

	for ( i = 0; i < STORAGE_DIRECTORY_COUNT; i++ )
	{
		storage_size += directories[i].entry_size * directories[i].entrys_count;
	}
	
	return -1;
}

static void storage_print( unsigned int directory, unsigned int out_dev ) /* return 0 or -1 if fail */
{
	if ( directory >= STORAGE_DIRECTORY_COUNT )
		return ;

	storage_index = directory;

	outf(out_dev, "\n   ==== DATA STORAGE ====\n" );

	DIR_PROP.print(out_dev);
}

storage_class_t storage = 
{
	STORAGE_START_ADDRESS,
	Ex_WriteData,
	Ex_ReadData,
	Ex_CheckRecord, 
	Ex_MemSet,
	storage_add,
	storage_find,
	storage_delete_entry,
	storage_delete_directory,
	storage_del_all,
	storage_print,
	storage_entrys_counter
};


/* ======================================================================================== */
/* ======================================================================================== */
/* ======================================================================================== */



/* ======== END OF DIRECTORY OF USER LIST 1 ======= */




































//first field of the storage entry must be string.
/* return index of directory into directories[] */
/* static int storage_find_properties_of_directory(unsigned int directory) */
/* { */
/* 	int i; */
		
/* 	for(i=0; &directories[i]; i++) */
/* 	{ */
/* 		if ( directories[i].directory_addr == directory ) */
/* 		{ */
/* 			return i; */
/* 		} */
/* 	} */

/* 	return STORAGE_ERR__WRONG_DIRECTORY; */
/* }  */
